package com.example.gateway.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.time.Duration;

@Component
public class IpLoggingFilter implements WebFilter {

    @Autowired
    private ReactiveStringRedisTemplate redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String path = exchange.getRequest().getPath().value();

        // 过滤只统计指定路径（你可以根据需求调整）
        if (!isTargetPath(path)) {
            return chain.filter(exchange);
        }

        // 获取真实客户端IP，优先X-Forwarded-For头
        String ip = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
        if (ip == null || ip.isEmpty()) {
            ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
        }

        String key = "ip:access:" + ip;
        long now = System.currentTimeMillis();

        // 打印访问日志，方便调试
        System.out.println("访问记录 -- IP: " + ip + ", 路径: " + path + ", 时间戳: " + now);

        // Redis异步更新：
        // 1）整体访问计数
        redisTemplate.opsForHash().increment(key, "count", 1).subscribe();
        // 2）更新时间戳
        redisTemplate.opsForHash().put(key, "lastAccess", String.valueOf(now)).subscribe();
        // 3）路径访问计数（hash key后缀":paths"存储每个路径的访问次数）
        redisTemplate.opsForHash().increment(key + ":paths", path, 1).subscribe();
        // 4）设置7天过期防止无限增长
        redisTemplate.expire(key, Duration.ofDays(7)).subscribe();
        redisTemplate.expire(key + ":paths", Duration.ofDays(7)).subscribe();

        return chain.filter(exchange);
    }

    private boolean isTargetPath(String path) {
        // 只统计以下路径访问，减少无效数据
        return path.startsWith("/api/ai/") || path.startsWith("/springbootn3op2l20/") || path.equals("/fallback");
    }
}

